package org.uoss.webapp.framework.context;

import java.util.ArrayList;
import java.util.List;

import org.apache.struts2.config.StrutsXmlConfigurationProvider;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.uoss.core.logging.ILogger;
import org.uoss.core.logging.ILoggerFactory;

import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.config.ConfigurationProvider;
import com.opensymphony.xwork2.inject.ContainerBuilder;
import com.opensymphony.xwork2.util.location.LocatableProperties;

public class WebappActionConfigProvider implements ConfigurationProvider {
	private static final ILogger logger = ILoggerFactory.getLogger(WebappActionConfigProvider.class);
	private List<ConfigurationProvider> configProviders;
	
	public WebappActionConfigProvider(){
		String[] actionConfigLocations = this.getActionConfigLocations();
		this.configProviders = new ArrayList<ConfigurationProvider>(actionConfigLocations.length);
		for(String location : actionConfigLocations){
			this.configProviders.add(new StrutsXmlConfigurationProvider(location,false,WebappBeansContext.getContextInstance().getServletContext()));
		}
	}
	
	@Override
	public void init(Configuration arg0) throws ConfigurationException {
		logger.info(WebappActionConfigProvider.class,"init()","Initialize struts configuration.");
		for(ConfigurationProvider configProvider : configProviders){
			configProvider.init(arg0);
		}
	}

	@Override
	public void register(ContainerBuilder arg0, LocatableProperties arg1) throws ConfigurationException {
		logger.info(WebappActionConfigProvider.class,"register()","Register struts configuration.");
		for(ConfigurationProvider configProvider : configProviders){
			configProvider.register(arg0, arg1);
		}
	}

	@Override
	public void loadPackages() throws ConfigurationException {
		for(ConfigurationProvider configProvider : configProviders)
			configProvider.loadPackages();
	}

	@Override
	public boolean needsReload() {
		for(ConfigurationProvider configProvider : configProviders){
			if(configProvider.needsReload()){
				return true;
			}
		}
		return false;
	}
	
	@Override
	public void destroy() {
		for(ConfigurationProvider configProvider : configProviders)
			configProvider.destroy();
	}
	
	private String[] getActionConfigLocations(){
		List<String> actionConfigResources = new ArrayList<String>();
		//actionConfigResources.add("classpath:META-INF/Web-Struts-Plugin.xml");
		actionConfigResources.add("classpath:com/uoss/webapp/**/ctx/Web-Struts-Context.xml");
		return this.getActionConfigLocations(actionConfigResources);
	}
	
	public String[] getActionConfigLocations(List<String> actionConfigResources){
		String[] actionConfigRealLocations = null;
		if (actionConfigResources == null || actionConfigResources.size() == 0) {
			logger.warn(this.getClass(), "getActionConfigLocations()", "Action config locations was null.");
			return actionConfigRealLocations;
		}
		try {
			Resource[] resources = null;
			String[] packageNames = {"META-INF","com/uoss/webapp"};
			PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
			List<String> configLocations = new ArrayList<String>();
			for(String ctxRes : actionConfigResources){
				resources = resolver.getResources(ctxRes);
				if (resources == null || resources.length == 0) {
					logger.info(this.getClass(), "getResourceRealLocations()", "Not found resource[" + ctxRes + "].");
					continue;
				}
				for(Resource res : resources){
					String location = res.getURL().getPath();
					for(String packageName : packageNames){
						if(location.indexOf(packageName)!=-1){
							String classpath = location.substring(location.lastIndexOf(packageName));
							if(!configLocations.contains(classpath)){
								configLocations.add(classpath);
								break;
							}
						}
					}
				}
			}
			actionConfigRealLocations = configLocations.toArray(new String[configLocations.size()]);
		}
		catch (Exception e) {
			logger.error(this.getClass(), "getResourceRealLocations()", "Getting bean context locations fail.", e);
		}
		return actionConfigRealLocations;
	}
}
